//
//  GameState.m
//  IssuesGame
//
//  Created by Martin Grider on 10/2/09.
//  Copyright 2009 Regents of the University of Minnesota
//

#import "GameState.h"
#import "Constants.h"

@implementation GameState

@synthesize score, playerX, playerY, playerPrevX, playerPrevY,title, size, tiles, perspectives, perspectiveImages, imagePath, askingQuestion;


// Init with data object read from xml file
- (id)initWithData: (NSData *)data {
	if (self = [super init]) {

		perspectives = [NSMutableDictionary new];
		tiles = [NSMutableArray new];
		
		NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
		[parser setDelegate:self];
		[parser parse];
		[parser release];
		
		int nTiles = [tiles count];
		size = 0;
		
		// Determine smallest board that will accommodate all tiles (including the "fixed" start and end tiles)
		while ( nTiles > ((size * size) -2) ) {
			size++;
		}

		// starting location of the "player" icon
		playerPrevX = playerX = 0;
		playerPrevY = playerY = (size - 1);

		// start with score of size+2 / 2 * absolute value of kGameScoreMovementDecrement
		score = (size + 2) * fabs(kGameScoreMovementDecrement);
		
		// subtract two, one for start and end
		int totTiles = ( size * size ) - 2;
		
		// Blank tile
		NSDictionary *blankTile = [NSMutableDictionary dictionaryWithObjectsAndKeys:kTilePerspectiveBlank, kTilePerspective, nil];
		
		// Fill out the board with blank tiles
		while (nTiles < totTiles) {
			[tiles addObject:blankTile];
			nTiles++;
		}

		[tiles sortUsingFunction:randomSort context:nil];

		// insert the start tile, and end tile
		NSDictionary *finishTile = [NSMutableDictionary dictionaryWithObjectsAndKeys:kTilePerspectiveFinish, kTilePerspective, nil];
		int finishTileIndex = size - 1;
		[tiles insertObject:finishTile atIndex:finishTileIndex];
		NSDictionary *startTile = [NSMutableDictionary dictionaryWithObjectsAndKeys:kTilePerspectiveStart, kTilePerspective, nil];
		int startTileIndex = ( size * (size -1) );
		[tiles insertObject:startTile atIndex:startTileIndex];

		//NSLog(@"tiles: %@",tiles);
		[self buildPerspectiveImages];
	}
	
	return self;
}


- (id)initFromSavedGame {
	
	if (self = [super init]) {
		score = [[[NSUserDefaults standardUserDefaults] objectForKey:kGameScore] intValue];
		playerPrevX = playerX = [[[NSUserDefaults standardUserDefaults] objectForKey:kGamePlayerX] intValue];
		playerPrevY = playerY = [[[NSUserDefaults standardUserDefaults] objectForKey:kGamePlayerY] intValue];
		title = [[NSUserDefaults standardUserDefaults] objectForKey:kGameTitle];
		imagePath = [[NSUserDefaults standardUserDefaults] objectForKey:kGameImagePath];
		tiles = [[NSUserDefaults standardUserDefaults] objectForKey:@"tiles"];
		perspectives = [[NSUserDefaults standardUserDefaults] objectForKey:@"perspectives"];
		size = [[[NSUserDefaults standardUserDefaults] objectForKey:kGameSize] intValue];
		int version = [[[NSUserDefaults standardUserDefaults] objectForKey:kGameSaveVersionKey] intValue];
		askingQuestion = [[[NSUserDefaults standardUserDefaults] objectForKey:kGameAskingQuestionKey] boolValue];

		if ( ! ( score && title && tiles && perspectives ) || version != kGameSaveVersion ) {
			return nil;
		}
		[self buildPerspectiveImages];
	}
	
	return self;
}


- (void)save {
	[[NSUserDefaults standardUserDefaults] setObject:title forKey:kGameTitle];
	[[NSUserDefaults standardUserDefaults] setObject:imagePath forKey:kGameImagePath];
	[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:score] forKey:kGameScore];
	[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:playerX] forKey:kGamePlayerX];
	[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:playerY] forKey:kGamePlayerY];
	[[NSUserDefaults standardUserDefaults] setObject:tiles forKey:@"tiles"];
	[[NSUserDefaults standardUserDefaults] setObject:perspectives forKey:@"perspectives"];
	[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:size] forKey:kGameSize];
	[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:kGameSaveVersion] forKey:kGameSaveVersionKey];
	[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:askingQuestion] forKey:kGameAskingQuestionKey];
	[[NSUserDefaults standardUserDefaults] synchronize];
}


- (void)buildPerspectiveImages {

	if ( perspectiveImages != nil ) {
		//NSLog(@"already have perspectiveImages, returning...");
		return;
	}
	perspectiveImages = [[NSMutableDictionary dictionaryWithCapacity:[perspectives count]] retain];

	// instantiate the perspective images
	for ( id perspective in perspectives ) {
		NSString *perspectiveName = [[perspectives valueForKey:perspective] valueForKey:kPerspectiveName];
		NSString *nameWithPrefix = [@"gamedocs/" stringByAppendingString:[[perspectives valueForKey:perspective] valueForKey:kPerspectiveImagePath]];
		NSString *perspectiveImagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:nameWithPrefix];
		UIImage *perspectiveImage = [[UIImage imageWithContentsOfFile:perspectiveImagePath] retain];

		[perspectiveImages setValue:perspectiveImage forKey:perspectiveName];

		if ( nil == perspectiveImage ) {
			NSLog(@"perspectiveImage for image: %@ is NIL!!!!?!!!?!?!?!?", perspectiveName);
		}
		[perspectiveImage release];
	}

}


#pragma mark -
#pragma mark NSXMLParserDelegate methods


- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
	NSLog(@"XML parse error: %@", [parseError description]);
}


- (void)parser:(NSXMLParser *)parser 
didStartElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI 
 qualifiedName:(NSString *)qualifiedName 
	attributes:(NSDictionary *)attributeDict {
	
	currentElement = elementName;
	
	if ( [currentElement isEqualToString:kElementGame] ) {
		title = [attributeDict objectForKey:kGameTitle];
	}
	else if ( [currentElement isEqualToString:kElementImage] ) {
		imagePath = [attributeDict objectForKey:kGameImagePath];
	}
	else if ( [currentElement isEqualToString:kElementPerspective] ) {
		// Set the current perspective
		currentPerspective = [NSMutableDictionary dictionaryWithDictionary:attributeDict];
		[currentPerspective retain];
		currentAnswers = [NSMutableArray new];
	}
	else if ( [currentElement isEqualToString:kElementFact] ) {
		// Create tile starting with perspective info
		currentTile = [NSMutableDictionary dictionaryWithObjectsAndKeys:
					   [currentPerspective objectForKey:kPerspectiveName],
					   kTilePerspective, 
					   nil];
		[currentTile retain];
	}
	
}



- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
	
	if ( [currentTile objectForKey:currentElement] ) {
		return;
	}

	// remove whitespace
	string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

	if ( [currentElement isEqualToString:kTileQuestion] ) {
		[currentTile setValue:string forKey:kTileQuestion];
	}
	if ([currentElement isEqualToString:kTileAnswer]) {
		[currentTile setValue:[NSNumber numberWithInt:[currentAnswers count]] forKey:kTileAnswer];

		[currentAnswers addObject:string];
	}
}


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
	if ( [elementName isEqualToString:kElementFact] ) {
		[currentTile setValue:kTileStatusUnanswered forKey:kTileStatus];
		// Tile is complete, add to tiles
		[tiles addObject:currentTile];
		[currentTile release];
	}
	if ( [elementName isEqualToString:kElementPerspective] ) {
		// Done with this perspective
		NSString *perspectiveName = [currentPerspective valueForKey:kPerspectiveName];
		[currentPerspective setValue:currentAnswers forKey:kPerspectiveAnswers];
		[perspectives setValue:currentPerspective forKey:perspectiveName];
		
		[currentAnswers release];
		[currentPerspective release];
	}
}


#pragma mark -
#pragma mark Querying Game State


- (Tile *)tileAtCurrentPlayerLocation {
	return [self tileAtRow:playerY andColumn:playerX];
}


- (Tile *)tileAtRow:(int)row andColumn:(int)column
{
	int index = [self indexOfRow:row andColumn:column];
	NSMutableDictionary *tileDictionary = [tiles objectAtIndex:index];
	NSString *perspectiveName = [tileDictionary valueForKey:kTilePerspective];
	NSDictionary *perspectiveDictionary = [perspectives valueForKey:perspectiveName];
	return [[[Tile alloc] initWithTileDictionary:tileDictionary andPerspectiveDictionary:perspectiveDictionary] autorelease];
}


- (int)indexOfRow:(int)row andColumn:(int)column
{
	if ( row > size - 1 || column > size - 1 ) {
		return -1;
	}

	return row * size + column;
}


- (BOOL)playerCanMoveUp {
	if ( playerY == 0 ) {
		return NO;
	}
	else {
		return YES;
	}
}


- (BOOL)playerCanMoveDown {
	if ( playerY == ( size -1) ) {
		return NO;
	}
	else {
		return YES;
	}
}


- (BOOL)playerCanMoveLeft {
	if ( playerX == 0 ) {
		return NO;
	}
	else {
		return YES;
	}
}


- (BOOL)playerCanMoveRight {
	if ( playerX == (size-1) ) {
		return NO;
	}
	else {
		return YES;
	}
}


/* TODO ...?
- (NSString *)description {
	NSString *description = [NSString stringWithFormat:@"title: %@\nimagePath: %@",title, imagePath];
	return description;
}
*/


#pragma mark -
#pragma mark Memory stuff


- (void)dealloc {
	[currentElement release];
	[perspectives release];
	[perspectiveImages release];
	[tiles release];
	[title release];
	[imagePath release];
    [super dealloc];
}


@end
